package zgame.bussiness;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import zgame.bean.Port;
import zgame.bean.Service;
import zgame.bean.Session;
import zgame.bean.User;
import zgame.bean.Service.FUNCTION;
import zgame.bean.Service.TYPE;
import zgame.dao.AuthenticateDao;
import zgame.main.Global;
import zgame.main.Initialize;
import zgame.main.Main;
import zgame.socket.DataPackage;
import zgame.socket.ProtocolConstants;
import zgame.socket.ServerConnection;
import zgame.utils.MD5;

public class GameServiceBussiness {
  private static Logger log = Logger.getLogger(GameServiceBussiness.class);

  public static void userJoinInInform(ServerConnection server, DataPackage inputDataPackage) throws SQLException {
    AuthenticateDao authenticateDao = AuthenticateDao.createInstance();
    String username = inputDataPackage.nextString();

    Session session = Global.sessionMap.get(username);
    if (session == null) {
      log.warn("GameServiceBussiness : userJoinInInform : user " + username + " has joined to GameService " + server.name
          + " without session in DefaultService");
      return;
    }

    Service gameService = Main.serviceController.getServiceById(server.name);
    session.setCurrentGameService(gameService);
    session.setOnline(true);

    // Cập nhật thông tin user cho GameService
    User user = authenticateDao.getUserInfo(username);

    DataPackage dataPackage = new DataPackage(ProtocolConstants.ResponseHeader.USER_INFO_REPONSE);
    dataPackage.putString(username);
    dataPackage.putInt(user.getMoney());
    dataPackage.putInt(user.getAvatarId());
    server.write(dataPackage);

    log.info("User " + username + " JOIN in server: " + gameService.getName());
    authenticateDao.close();

    gameService.onUserJoinIn(user);
    FriendBussiness.onUserJoinToGameService(username, server);
  }

  public static void userOutInform(ServerConnection server, DataPackage inputDataPackage) {
    String username = inputDataPackage.nextString();

    Session session = Global.sessionMap.get(username);
    if (session == null) {
      log.warn("GameServiceBussiness : userOutInform : user " + username + " has joined to GameService " + server.name
          + " without session in DefaultService");
      return;
    }

    Service gameService = Main.serviceController.getServiceById(server.name);
    if ((session.getCurrentGameService() != null) && session.getCurrentGameService().getId().equals(gameService.getId())) {
      session.setCurrentGameService(null);
      session.setOnline(false);
      gameService.onUserGetOut(username);
    }

    log.info("User " + username + " OUT server: " + gameService.getName());
  }

  public static void updateGameServiceInfo(ServerConnection server, DataPackage inputDataPackage) {
    int concurrentUser = inputDataPackage.nextInt();
    Service gameService = Main.serviceController.getServiceById(server.name);
    gameService.setCocurrentUser(concurrentUser);

    // log.info("Receive game service info from: " + gameService.getName());
  }

  public static void authenRequestHandle(ServerConnection server, DataPackage inputDataPackage) {
    String username = inputDataPackage.nextString();
    String salt1 = inputDataPackage.nextString();

    Session session = Global.sessionMap.get(username);
    if (session == null) {
      DataPackage dataPackage = new DataPackage(ProtocolConstants.ResponseHeader.SESSION_NOT_EXIST);
      dataPackage.putString(username);
      server.write(dataPackage);
      return;
    }

    String encodeData = MD5.toBase64((session.getId() + salt1).getBytes());
    DataPackage dataPackage = new DataPackage(ProtocolConstants.ResponseHeader.SESSION_RESPONSE);
    dataPackage.putString(username);
    dataPackage.putString(encodeData);
    server.write(dataPackage);

    log.info("Response sessionId for user " + username);
  }

  public static void validGameServiceInfo(ServerConnection server, DataPackage inputDataPackage) {
    // Get value from data package
    String id = inputDataPackage.nextString();
    String name = inputDataPackage.nextString();
    String description = inputDataPackage.nextString();
    String function = inputDataPackage.nextString();
    String type = inputDataPackage.nextString();
    String validateKey = inputDataPackage.nextString();
    String url = inputDataPackage.nextString();
    String portName = inputDataPackage.nextString();
    int portValue = inputDataPackage.nextInt();
    String portDescription = inputDataPackage.nextString();
    int cocurrentUser = inputDataPackage.nextInt();
    int maxUser = inputDataPackage.nextInt();
    
    // Create port
    Port port = new Port();
    port.setName(portName);
    port.setValue(portValue);
    port.setDescription(portDescription);
    
    // Create service
    Service service = new Service(id, name);
    service.setDescription(description);
    service.setFunction(FUNCTION.valueOf(function.toUpperCase()));
    service.setType(TYPE.valueOf(type.toUpperCase()));
    service.setValidateKey(validateKey);
    service.setUrl(url);
    service.addPort(port);
    service.setCocurrentUser(cocurrentUser);
    service.setMaxUser(maxUser);
    
    if (isServiceValid(service)) {
      Main.serviceController.storeService(service);
      server.name = service.getId();
      service.setServer(server);

      log.info("SERVICE IS REGISTED SUCCESSFULLY: " + service.toString());

      DataPackage dataPackage = new DataPackage(ProtocolConstants.RequestHeader.GAME_SERVICE_REGISTER_SUCCESS_REQUEST);
      dataPackage.putInt(Global.TIME_OUT);
      dataPackage.putInt(Global.DATA_UPDATE_SEQUENCE_TIME);
      server.write(dataPackage);
    } else {
      log.warn("Service is invalid: " + service.toString());
      server.write(new DataPackage(ProtocolConstants.RequestHeader.GAME_SERVICE_REGISTER_FAIL_REQUEST));
      server.write(new DataPackage(ProtocolConstants.RequestHeader.CLOSE_CONNECTION_REQUEST));
      server.detroy();
    }
  }
  
  private static boolean isServiceValid(Service service) {
    Service serviceFromConfig = Initialize.serviceConfigReader.getServiceFromConfig(service.getId());
    if (serviceFromConfig == null) {
      return false;
    }
    
    if (service.getValidateKey() == null) {
      return false;
    }
    return service.getValidateKey().equals(serviceFromConfig.getValidateKey());
  }

  public static void releaseAllConnectionToUser(ServerConnection server) {
    Service gameService = Main.serviceController.getServiceById(server.name);
    List<User> users = new ArrayList<User>(gameService.getUserMap().values());
    for (User user : users) {
      AuthenticateBussiness.signOut(user.getUsername());
    }
  }
}
